package cz.artin.adp.commons.db;

import cz.artin.gemini.shared.domain.DomainObject;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author londrusek | libor.ondrusek@artin.cz
 */
@SuppressWarnings({"unchecked","rawtypes"})
public abstract class AbstractCrudDao<T extends DomainObject> implements CrudDao<T> {

  @PersistenceContext
  private EntityManager em;

  private Class<T> type;

  
public AbstractCrudDao() {
	Type t = getClass().getGenericSuperclass();
	ParameterizedType pt = (ParameterizedType) t;
	type = (Class) pt.getActualTypeArguments()[0];
  }

  @Override
  public TypedQuery query(String jpql) {
	if (jpql.contains("{type}")) {
	  jpql = jpql.replaceAll("\\{type\\}", type.getCanonicalName());
	}
	return em.createQuery(jpql, type);
  }

  @Override
  public final T get(Long id) {
	return em.find(type, id);
  }

  @Override
  public final List<T> getAll() {
	return em.createQuery("FROM " + type.getCanonicalName()).getResultList();
  }

  @Override
  public final T save(T entity) {
	em.persist(entity);
	return get(entity.getId());
  }

  @Override
  public final T update(T entity) {
	em.merge(entity);
	return get(entity.getId());
  }

  @Override
  public final void delete(T entity) {
	em.remove(entity);
  }
}
